package cn.mw.cmdb.entity;

import cn.mw.cmdb.exception.InputRequireException;
import cn.mw.cmdb.service.impl.PropertyNameValue;
import cn.mw.components.mongodb.anno.AutoId;
import cn.mw.components.mongodb.anno.CMDBProperty;
import com.alibaba.nacos.common.utils.CollectionUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import static cn.mw.cmdb.util.ValConvertUtil.booleanValueConvert;

@Data
public class PropertyInfo implements Serializable {
    public static final String PropertyIdPefix = "mw_";

    public static final String allPropertyMap = "allPropertyMap";
    @Schema(description = "id")
    @CMDBProperty(id = true, searchType = PropertyTypeString.ID, searchPrefix = "_")
    @AutoId
    private String id;

    //由于mongodb保存数据时,会在id字段前加入一个下划线
    //因此在生成查询条件的时候,也许加入一个前缀
    private String searchPrefix;

    private String modelId;

    //属性名称
    private String name;

    //属性描述
    private String desc;

    //属性排序
    private Integer sortNum;

    //属性分类
    private String propertyCatologName;

    // 属性分类
    private List<PropertyCategoryVo> propertyCatologList;

    //属性类型
    private PropertyTypeRef propertyTypeRef;

    //当该属性值需要从外部服务获取时使用
    private ForeignKey foreignKey;

    //告警标识
    private Boolean enableAlert = false;

    //属性是否显示  关闭后，查询新增修改列表全都不显示
    private Boolean enableShow;
    //属性list列表默认显示，如果enableShow为false,该字段不生效
    //实例列表表头字段显示
    private Boolean defaultListVisible;

    //字段是否纳入流程管理
    private Boolean enableProManage;

    //字段权限
    private Set<FieldAuthType> fieldAuthTypes;

    //视图限制
    private Set<FieldViewAuthType> fieldViewAuthTypes;

    //视图限制
    private List<FieldViewAuthVo> fieldViewAuthList;

    private List<FinanceModelFieldViewAuthVo> financeViewAuthList;

    //系统内部控制属性
    private boolean sysInternal = false;

    //系统内部控制属性
    private boolean keywordSearch = false;
    //字段来源(自定义，内置，父模型)
    private String propertySource;


    public PropertyType getPropertyType() {
        if (propertyTypeRef != null) {
            return PropertyTypeManage.getPropertyType(propertyTypeRef.getTypeId());
        }
        return null;
    }

    //验证实例字段值是否符合要求
    public boolean validateValue(Object value) throws Exception {
        if(value instanceof String){
            return doValidateValue(value ,(data)->{
                return !StringUtils.hasText(data.toString().trim());});
        }
        return doValidateValue(value,(data)->{return null == data;});
    }

    private boolean doValidateValue(Object value , Function<Object ,Boolean> function){
        //验证是否必填
        if (null != fieldAuthTypes
                && fieldAuthTypes.contains(FieldAuthType.require)
                && function.apply(value)){
            throw new InputRequireException(new Object[]{name});
        }
        return true;
    }

    public PropertyNameValue getValue(Map dataMap){
        if (dataMap != null && dataMap.containsKey(id)) {
            Object valueObj = dataMap.get(id);
            return PropertyNameValue.builder().name(id).value(valueObj).build();
        }
        if (dataMap != null && dataMap.containsKey(name)) {
            Object valueObj = dataMap.get(id);
            return PropertyNameValue.builder().name(id).value(valueObj).build();
        }
        return null;
    }

    public boolean isDefaultListVisible() {
        if (null == enableShow || enableShow == false) {
            return false;
        }
        return booleanValueConvert(defaultListVisible);
    }

    public Set<FieldViewAuthType> getFileViewAuth(String viewType, String financeParentModelId) {
        Set<FieldViewAuthType> fieldViewAuthTypes = null;
        // 当配置了金融元父模型权限时以父模型配置为主
        if (StringUtils.hasText(financeParentModelId) && CollectionUtils.isNotEmpty(getFinanceViewAuthList())) {
            for (FinanceModelFieldViewAuthVo fieldViewAuthVo : getFinanceViewAuthList()) {
                if (financeParentModelId.equals(fieldViewAuthVo.getModelId())) {
                    return fieldViewAuthVo.getFieldViewAuthTypes();
                }
            }
        }
        if (CollectionUtils.isNotEmpty(getFieldViewAuthList())) {
            for (FieldViewAuthVo fieldViewAuthVo : getFieldViewAuthList()) {
                if (viewType.equals(fieldViewAuthVo.getViewType())) {
                    fieldViewAuthTypes = fieldViewAuthVo.getFieldViewAuthTypes();
                    break;
                }
            }
        } else {
            fieldViewAuthTypes = getFieldViewAuthTypes();
        }
        return fieldViewAuthTypes;
    }
}
